
/**对象池接口 */
   interface IPool<T>
  {
       Allocate():T;

      Recycle(obj:T): boolean;
  }

/**对象池工厂接口 */
   interface IObjectFactory<T>
  {
       Create():T;
  }

  /**对象池基类 */
    abstract class Pool<T> implements IPool<T>
  {
      protected  mCacheStack:Array<T> = new Array<T>();
      public  mUsingArray:Array<T> = new Array<T>();
      public get CacheStackCount():Number
      {
        return this.mCacheStack.length;
      }

 
      public get  UsingCount():Number
      {
        return this.mUsingArray.length;
      }


      protected mFactory :IObjectFactory<T> ;


      public  Allocate():T
      {
          let obj= this.mCacheStack.length > 0 ? this.mCacheStack.pop() :this.mFactory.Create();
          this.mUsingArray.push(obj);
          return obj;
      }

      public abstract  Recycle(obj:T ):boolean;
  }

  /**对象池工厂 */
 class CustomObjectFactroy<T> implements IObjectFactory<T>
  {
      private  mFactroyMethod:()=>T;

      constructor(factroyMethod:()=>T)
      {
        this.mFactroyMethod = factroyMethod;
      }
      
      public  Create():T
      {
          return this.mFactroyMethod();
      }
  }

    /**简单对象池 */
    export default  class SimpleObjectPool<T> extends Pool<T>
    {
         mResetMethod:Function;

         constructor(factroyMethod:()=>T, resetMethod:Function= null, initCount:number = 0)
         { 
            super();
            this.mFactory = new CustomObjectFactroy<T>(factroyMethod);
            this.mResetMethod = resetMethod;
 
             for (var i = 0; i < initCount; i++)
             {
                this.mCacheStack.push(this.mFactory.Create());
             }
         }
 

        public  Recycle(obj:T ):boolean
        {
          if ( this.mCacheStack.indexOf(obj)>-1) 
          {
              return;
          } 
            if (this.mResetMethod != null)
            {
                this.mResetMethod(obj);
            }
            let index=this.mUsingArray.indexOf(obj);
            if (index>-1) 
            {
                this.mUsingArray.splice(index,1);
            }
            this.mCacheStack.push(obj);
            return true;
        }

        public RecycleAll()
        {
            for (let index = 0; index < this.mUsingArray.length; index++) 
            {
                const element = this.mUsingArray[index];
                this.mCacheStack.push(element);
            }
            this.mUsingArray.length=0;
        }

    }

